package com.yesep.learn.design.structural.proxy;

/**
 * 代理模式（Proxy Pattern）是一种结构型设计模式，在程序设计中用于为其他对象提供一种代理，以控制对这个对象的访问。
 * 这种模式通过引入一个代理对象来间接访问目标对象，从而实现了对目标对象的控制和增强。
 * 以下是关于代理模式的详细解析：
 * <p>
 * 一、定义与原理
 * 代理模式的核心思想是将客户端与实际执行功能的对象分离，引入一个中介层（代理层），由代理对象来决定是否和如何访问实际对象。
 * 代理对象可以在客户端和目标对象之间起到中介的作用，并可以在不修改目标对象代码的情况下，添加额外的功能，如访问控制、延迟加载、日志记录等。
 * <p>
 * 二、组成角色
 * 代理模式主要包含以下三个角色：
 * <p>
 * 抽象主题（Subject）接口：定义了代理和真实对象共同实现的接口，这样在任何使用真实对象的地方都可以使用代理对象。
 * 真实主题（Real Subject）类：实际执行逻辑的类，代理模式的目的是控制对这个类的访问。
 * 代理（Proxy）类：包含对真实主题的引用，它实现了与真实主题相同的接口，并可能在调用真实主题对象之前或之后执行额外的处理。
 * 三、优点
 * 增强了对原始对象的控制：代理模式允许在客户端和原始对象之间添加一个中介层，从而可以控制对原始对象的访问。
 * 提高了代码的灵活性和可扩展性：通过代理对象，可以在不修改原始对象代码的情况下，添加额外的功能。
 * 实现了延迟加载：代理对象可以延迟原始对象的创建和初始化，直到真正需要时才进行，从而节省了系统资源。
 * 增加了系统的安全性：代理可以控制对实际对象的访问权限，进行身份验证或其他安全措施，确保只有具有适当权限的客户端才能访问对象。
 * 四、应用场景
 * 代理模式适用于多种场景，包括但不限于：
 * <p>
 * 远程对象访问：在远程通信中，代理可以作为本地的代表来代理远程对象，隐藏实际对象位于远程位置的事实。
 * 控制对原始对象的访问权限：保护代理可以在执行操作之前进行权限检查，确保满足特定条件的客户端才能访问对象。
 * 延迟加载：当对象的创建开销很大时，可以使用虚拟代理进行懒加载，即在真正需要对象时才创建它。
 * 日志记录和监控：代理对象可以在调用目标对象的方法前后添加日志记录或其他监控功能。
 * 缓存：代理可以用于缓存昂贵的操作结果，以便在后续请求中快速访问。
 * 五、类型
 * 代理模式根据代理对象的创建时机和方式，可以分为静态代理和动态代理。
 * <p>
 * 静态代理：由程序员创建或工具生成代理类的源码，再编译代理类。静态代理在程序运行前就已经存在代理类的字节码文件，代理类和委托类的关系在运行前就确定了。
 * 动态代理：在实现阶段不用关心代理类，而在运行阶段才指定哪一个对象。动态代理通过反射机制在运行时动态地创建代理对象。
 */
public class Main {
    public static void main(String[] args) {
        ILogger jdkLogger = new JDKLogger(Main.class.getName());
        //静态代理
        ILogger staticLoggerProxy = new StaticLoggerProxy(Main.class.getName());
        DynamicLoggerProxy dynamicLoggerProxy = new DynamicLoggerProxy(jdkLogger);

        String message1 = "How are you?";
        String message2 = "I’m fine.Thank you.";
        jdkLogger.log(message1);
        staticLoggerProxy.log(message1);
        dynamicLoggerProxy.log(message1);
        jdkLogger.log(message2);
        staticLoggerProxy.log(message2);
        dynamicLoggerProxy.log(message2);

    }
}
